#include <stdio.h>
#include <string.h>
#include <string.h>
#include <stdlib.h>
#include "assembler.h"
#include "definitions.h"
#include "helpers.h"
#include "entities.h"

ArgumentType argType;
char currentLine[LINE_L];
char fixedLine[LINE_L];
char labelName[LABEL_L];
int lineNumber=0;
char *fileName;
boolean labelExist=false;
int labelCounter=0;
int externLabelCounter=0;
int entryLabelCounter=0;
char *currentArg;
char *currentCmd;
int labelsCounterInLine=0;
int dataCounter=0;
int instructionCounter=0;
int currentInstructionCounter = 0;
long memory[MEMORY_SIZE];
int cmdIndex=-1;
boolean errorWasFound=false;
PassNumber passNumber=First;
LabelsList Labels[LABELS_NUMBER];
ExternLabelsList ExternLabels[LABELS_NUMBER];
EntriesLabelsList EnteriesLabels[LABELS_NUMBER];
ObjectsList Objects[OBJECTS_SIZE];
static const char *operandTypesDesc[] ={"Source", "Destination"};
RegistersList Registers[REGISTERS_NUMBER]= {
		{0,"r0"},
		{1,"r1"},
		{2,"r2"},
		{3,"r3"},
		{4,"r4"},
		{5,"r5"},
		{6,"r6"},
		{7,"r7"}
};
/*commands are automatically assigned to a suitable method according the operands*/
CommandsList Commands[COMMANDS_NUMBER]={
		{"mov", 0, &ParseTwoOperands},
		{"cmp", 1, &ParseTwoOperands},
		{"add", 2, &ParseTwoOperands},
		{"sub", 3, &ParseTwoOperands},
		{"not", 4, &ParseOneOperand},
		{"clr", 5, &ParseOneOperand},
		{"lea", 6, &ParseTwoOperands},
		{"inc", 7, &ParseOneOperand},
		{"dec", 8, &ParseOneOperand},
		{"jmp", 9, &ParseOneOperand},
		{"bne", 10, &ParseOneOperand},
		{"red", 11, &ParseOneOperand},
		{"prn", 12, &ParseOneOperand},
		{"jsr", 13, &ParseOneOperand},
		{"rts", 14, &ParseNoOperands},
		{"stop",15, &ParseNoOperands}
};

/*
int main(int argc,char* argv[]):
Purpose: Write to output files if needed.
How:  Running on the input files, on every iterate copying the current file name to new memory allocation,
 	  then using "start" function to start the assembler.
Parameters: File Name or more, without extension (FileName.*).
Return value: if bad syntax while running the Program EXIT_FAILURE, otherwise EXIT_SUCCESS.
 */
int main(int argc,char* argv[])
{
	char *filePath;
	int i;
	if (argc == 1)
	{
		printf("Error - Missing arguments, At least one Input Data File is needed!\n");
		Usage();
		return EXIT_FAILURE;
	}

	for(i=1; i < argc; i++)
	{
		if(i > 1)
			Reset();
		filePath = (char*) malloc ( (int)strlen(argv[i]) + (int)strlen(AS_EXTENSION) + 1);
		strcpy (filePath, argv[i]);
		strcat (filePath, AS_EXTENSION);
		Start(filePath);/*start assemble*/
		free(filePath);
		free(fileName);
	}
	return EXIT_SUCCESS;
}

/*
void Start(char filePath[]):

Purpose: To preform two passes on every current file,
How: Running twice on the file with "fgets", and sending to the assembler for parsing.
Parameters: String Holds the file name.
Return value: Non.
*/
void Start(char filePath[])
{
	char fileName[FILE_PATH_L];
	char *ch;

	if(strlen(filePath) > FILE_PATH_L)
	{
		/*maximum file path length is 200*/
		printf("File %s length exceeded the maximum length of:%d\n", filePath,FILE_PATH_L);
		return;
	}
	else
	{
		FILE *file;
		char line[LINE_L];
		char *res;
		file = fopen(filePath, "r");
		if(file)
		{
			lineNumber = 0;
			passNumber = First;
			printf("\nStart reading file %s\n", filePath);
			res = fgets(line,LINE_L, file);
			if(!res)
			{
				printf("File %s is empty\n\n", filePath);
				return;
			}
			while(res)
			{
				lineNumber++;
				Assemble(line);
				res = fgets(line, LINE_L, file);
			}
			printf("Finish reading file first pass %s\n", filePath);

			if(!errorWasFound)
			{
				UpdateAddressForDataLabels();

				/*second pass*/
				passNumber = Second;
				ResetIterate();

				fseek(file, 0,SEEK_SET);
				res =fgets(line, LINE_L, file);
				while(res)
				{
					lineNumber++;
					Assemble(line);
					res = fgets(line, LINE_L, file);
				}
				printf("Finish reading file second pass %s\n", filePath);
			}

			if(!errorWasFound)
			{
				strcpy(fileName, filePath);
				ch = strrchr(fileName, '.');
				*ch = '\0';
				WriteFiles(fileName);
				printf("Finish writing files output for %s\n\n", filePath);
			}

			fclose(file);
		}
		else
		{
			printf("\nCannot open file %s\n\n",filePath);
			return;
		}
	}
}

/*
void ResetIterate():

Purpose: After second pass for reset the following values for the next iterate.
How: Reset to zero.
Parameters: Non.
Return value: Non.
*/
void ResetIterate()
{
	instructionCounter=0;
	lineNumber=0;
	externLabelCounter=0;
	errorWasFound = false;
}

/*
void Reset()

Purpose: before assemble another file needs to reset the relevant parameters
How: Reset to zero
Parameters: Non.
Return value: Non.
 */
void Reset()
{
	if(labelCounter > 0)
		memset(Labels, 0, (labelCounter-1) * sizeof(*Labels));
	if(externLabelCounter > 0)
		memset(ExternLabels, 0, (externLabelCounter-1) * sizeof(*ExternLabels));
	if(entryLabelCounter > 0)
		memset(EnteriesLabels, 0, (entryLabelCounter-1) * sizeof(*EnteriesLabels));
	if(instructionCounter>0)
		memset(Objects, 0, (instructionCounter-1) * sizeof(*Objects));

	labelExist=false;
	labelCounter=0;
	entryLabelCounter=0;
	labelsCounterInLine=0;
	dataCounter=0;
	instructionCounter=0;
	currentInstructionCounter = 0;
	memory[MEMORY_SIZE]=0;
	cmdIndex=-1;
	passNumber=First;

	ResetIterate();
}

/*
void Assemble(char *line):

Purpose:
How:
Parameters:
Return value: Non.
*/
void Assemble(char *line)
{
	strncpy(currentLine, line,LINE_L);
	strncpy(fixedLine, line,LINE_L);
	currentArg = strtok(currentLine, " \t\n");
	labelsCounterInLine=0;
	int currentLabelCounter = labelCounter;

	do{
		/*get argument type*/
		argType = GetArgumentType(currentArg, &cmdIndex, Registers, Commands);
		switch(argType)
		{
			case Comment:
			case Empty:
			{
				return;
			}
			case Unknown:
			{
				printf("Unknown syntax. Line number %d\n", lineNumber);
				errorWasFound = true;
				return;
			}
			case Label:
			{
				labelsCounterInLine++;
				if(labelsCounterInLine > 1)
				{
					printf("Label is not allowed in this position. Line number %d\n", lineNumber);
					errorWasFound=true;
					return;
				}
				/*put label in memory only in first pass*/
				if(passNumber == First)
				{
					memset(labelName, 0, LABEL_L);
					strncpy(labelName, currentArg, strlen(currentArg) -1);
					labelExist = true;

				}
				currentArg = strtok(NULL, " \t\n");

				break;
			}
			case InstructionData:
			case InstructionString:
			{
				/*in second pass ignore*/
				if(passNumber == Second)
					return;
				/*add label to labels table*/
				if(labelExist)
				{
					strcpy(Labels[labelCounter].name, labelName);
					Labels[labelCounter].decimalAddress = 0;
					Labels[labelCounter].value = dataCounter;
					Labels[labelCounter].type = DATA_CODE;
					labelCounter++;
					labelExist = false;

				}

				/*parse data from .data or .string and increase the data counter*/
				if(!ParseData(argType))
				{
					errorWasFound = true;
					printf("Failed parse data. Line number %d\n", lineNumber);
				}

				return;
			}

			case InstructionExtern:
			{
				currentArg = strtok(NULL, " \t\n");/*get extern label*/

				if(passNumber == Second)
					return;


				if(currentArg)
				{
					strcpy(ExternLabels[externLabelCounter].name, currentArg);
					ExternLabels[externLabelCounter].decimalAddress = 0;
					externLabelCounter++;
				}
				else
				{
					printf("Could not read label after extern instruction. Line number %d\n", lineNumber);
					errorWasFound = true;
				}
				return;
			}

			case InstructionEntry:
			{
				currentArg = strtok(NULL," \t\n");/*get entry label*/

				if(passNumber == Second)
				{
					/*update enteries addresses. in second pass we know the addresses*/
					UpdateEntryAddress(argType, currentArg);
					return;
				}

				if(currentArg)
				{
					strcpy(EnteriesLabels[entryLabelCounter].name, currentArg);
					EnteriesLabels[entryLabelCounter].decimalAddress = 0;/*we don't know the address yet*/
					entryLabelCounter++;
				}
				else
				{
					printf("Could not read entry label. Line number %d\n", lineNumber);
					errorWasFound=true;
				}
				return;
			}

			case Command:
			{
				/*only in first pass add the existing label*/
				if(passNumber == First && labelExist)
				{
					strcpy(Labels[labelCounter].name, labelName);
					Labels[labelCounter].decimalAddress = BASE_ADDRESS + instructionCounter;
					Labels[labelCounter].value = instructionCounter;
					Labels[labelCounter].type = CODE_CODE;
					labelCounter++;
					labelExist = false;
				}

				/*parse command*/
				if(!ParseCommand(cmdIndex))
				{
					errorWasFound=false;
					printf("Could not parse command %s. Line number %d\n", currentArg, lineNumber);
				}

				if (labelsCounterInLine == 1)
				{
					Labels[currentLabelCounter].codeSize = instructionCounter - currentInstructionCounter;
				}

				return;
			}
			default:
			{
				printf("Unknown instruction. Line number %d\n", lineNumber);
				errorWasFound = true;
				return;
			}
		}
	}while(currentArg != NULL && argType != Empty);
}

/*
boolean ParseData(ArgumentType argType):

Purpose: parsing the argument data type of .string or .data
How: if argument type is .string then count the characters
	 if argument type is .data then get data separated by comma and count the numbers
Parameters: enum argument type
Return value: true if parsing data was done successfully otherwise false (enum boolean)
*/
boolean ParseData(ArgumentType argType)
{
	int res, data,position,i;
	char *ch;

	switch(argType)
	{
		/*needs to read data (numbers)*/
		case InstructionData:
		{
			currentArg = strtok(NULL, " , \t");
			if(!currentArg)/*no numbers or incorrect delimiter*/
			{
				printf("Cannot red data after .data. Line number %d\n", lineNumber);
				return false;
			}
			while(currentArg)/*as long as number was found*/
			{
				res = sscanf(currentArg, "%d", &data);
				if(res > 0)
					memory[dataCounter++] = MASK_BITS & data;/*save data in memory*/

				currentArg = strtok(NULL, " , \t");/*get next number*/
			}
			break;
		}

		case InstructionString:
		{
			currentArg = strtok(NULL, " \t\n");/*get string*/
			if(!currentArg)/*string is empty*/
			{
				printf("Empty string after .string. Line number %d\n", lineNumber);
				return false;
			}

			/*get the position where string starts*/
			position = strlen(fixedLine) - strlen(currentArg)-1;
			ch = strrchr(fixedLine, '"');/*string must starts and ends with " sign*/
			if(fixedLine[position] != '"' || !ch)/*incorrect format*/
			{
				printf("Invalid format string. Line number %d\n", lineNumber);
				return false;
			}

			position+=1;/*starts after "*/
			for(i=position; fixedLine[i]!= '"'; i++)
			{
				memory[dataCounter++] = fixedLine[i];/*save char in memory*/
			}
			/*for \0*/
			dataCounter++;
			break;
		}
		default:
			return false;
	}
	return true;
}

/*
boolean ParseCommand(int cmdIndex)

Purpose: parsing the command
How: get the command from line update the command bits
	 get the commands parameters: type, combinations and dbl then update the relevant bits
Parameters: command index
return value: true if parsing command was done successfully  otherwise false (enum boolean)
 */
boolean ParseCommand(int cmdIndex)
{
	int type, res, comb1, comb2, dbl;
	char *ch;
	char commandName[COMMAND_LINE_L];
	currentInstructionCounter = instructionCounter;

	if (cmdIndex < 0 || cmdIndex > COMMANDS_NUMBER)
	{
		printf("Not supported command index %d. Line number %d\n", cmdIndex, lineNumber);
		return false;
	}

	/*get command name*/
	strcpy(commandName, currentArg);
	ch = strtok(commandName, "/");
	if (!ch)
	{
		printf("Could not read command. Line number %d\n", lineNumber);
		return false;
	}
	/*get command type*/
	ch = strtok(NULL, "/,");
	if (!ch)
	{
		printf("Could not read command type. Line number %d\n", lineNumber);
		return false;
	}
	/*read type value*/
	res = sscanf(ch, "%d", &type);
	if (!res)
	{
		printf("Could not read type. Line number %d\n", lineNumber);
		return false;
	}
	/*update command type and base address*/
	Objects[instructionCounter].machineCode = Objects[instructionCounter].machineCode | (type << 16);
	Objects[instructionCounter].decimalAddress = BASE_ADDRESS + instructionCounter;
	strcpy(Objects[instructionCounter].type, "a");

	if (type > 1)/*type could not be bigger than 1 valid values are (0,1)*/
	{
		printf("Invalid command type value. Line number %d\n", lineNumber);
		return false;
	}

	if (type == 1)
	{
		/*get combinations*/
		ch = strtok(NULL, "/,");
		if (!ch)
		{
			printf("Invalid combination. Line number %d\n", lineNumber);
			return false;
		}
		res = sscanf(ch, "%d", &comb1);
		if (!res)
		{
			printf("Could not read command first combination. Line number %d\n", lineNumber);
			return false;
		}
		if (comb1 > 1 || comb1 < 0)/*comb valid values are 0,1*/
		{
			printf("Invalid (first) combination value. Line number %d\n", lineNumber);
			return false;
		}
		/*update left comb*/
		Objects[instructionCounter].machineCode = Objects[instructionCounter].machineCode | (comb1 << 1);

		ch = strtok(NULL, "/,");/*get second comb*/
		if (!ch)
		{
			printf("Invalid combination. Line number %d\n", lineNumber);
			return false;
		}
		res = sscanf(ch, "%d", &comb2);
		if (!res)
		{
			printf("Could not read command second combination. Line number %d\n", lineNumber);
			return false;
		}
		if (comb2 > 1 || comb2 < 0)
		{
			printf("Invalid (second) combination value. Line number %d\n", lineNumber);
			return false;
		}
		/*update right comb*/
		Objects[instructionCounter].machineCode = Objects[instructionCounter].machineCode | comb2;
	}

	/*get dbl value*/
	ch = strtok(NULL, "/,");
	if (!ch)
	{
		printf("Could not get command dbl value. Line number %d\n", lineNumber);
		return false;
	}
	res = sscanf(ch, "%d", &dbl);
	if (!res)
	{
		printf("Could not read command dbl value. Line number %d\n", lineNumber);
		return false;
	}
	if (dbl < 0 || dbl > 1)/*dbl valid values are 0,1*/
	{
		printf("Invalid command dbl value. Valid values are 0,1. Line number %d\n", lineNumber);
		return false;
	}
	/*update dbl value*/
	Objects[instructionCounter].machineCode = Objects[instructionCounter].machineCode | (dbl << 17);

	/*update command index*/
	Objects[instructionCounter].machineCode = Objects[instructionCounter].machineCode | (cmdIndex << 12);


	/*execute suitable method*/
	Commands[cmdIndex].cmdHandler();

	instructionCounter++;

	return true;

}

/*
boolean ParseOperand(OperandType opType)
Purpose: parsing the operand by operand type
How: find the address method and parse the operand by the requested address method
Parameters: OperandType enum Source or Destination
return value: true if parsing operand was done successfully otherwise false (enum boolean)
 */
boolean ParseOperand(OperandType opType)
{
	int regIndex, labelAddress, number;
	char dataIndex[COMMAND_LINE_L];
	char label[COMMAND_LINE_L];
	char operand[COMMAND_LINE_L];

	/*check if operand is a register*/
	if(IsRegister(&regIndex, currentCmd, Registers))
	{
		if(IsLegalAddressingMethod(cmdIndex, opType, Register))
		{
			/*update source bits*/
			if(opType == Source)
			{
				Objects[currentInstructionCounter].machineCode = Objects[currentInstructionCounter].machineCode | (regIndex<<7);
				Objects[currentInstructionCounter].machineCode = Objects[currentInstructionCounter].machineCode | (Register<<10);
			}
			else/*update destination bits*/
			{
				Objects[currentInstructionCounter].machineCode = Objects[currentInstructionCounter].machineCode | (regIndex<<2);
				Objects[currentInstructionCounter].machineCode = Objects[currentInstructionCounter].machineCode | (Register<<5);
			}
		}
		else
		{
			errorWasFound = true;
			printf("Illegal addressing method Register for %s operand. Line number %d\n", operandTypesDesc[opType], lineNumber);
			return false;
		}
		return true;
	}

	/*check if operand is a label*/
	if(IsValidOperandLabel(currentCmd, Registers, Commands))
	{
		if(IsLegalAddressingMethod(cmdIndex, opType, Direct))
		{
			if(opType == Source)
				Objects[currentInstructionCounter].machineCode = Objects[currentInstructionCounter].machineCode | (Direct<<10);
			else
				Objects[currentInstructionCounter].machineCode = Objects[currentInstructionCounter].machineCode | (Direct<<5);

			instructionCounter ++;
			Objects[instructionCounter].decimalAddress = BASE_ADDRESS + instructionCounter;
			if(passNumber == Second)/*in second pass we need to insert the label address*/
			{
				labelAddress = GetLabelAddress(currentCmd, Labels, ExternLabels);
				Objects[instructionCounter].machineCode = labelAddress;

				/*address was not found*/
				if(labelAddress == -1)
				{
					printf("Could not find label %s address. Line number %d\n", currentCmd, lineNumber);
					return false;
				}
				/*external label*/
				if(labelAddress == -2)
				{
					/*update extern label*/
					ExternLabels[externLabelCounter].decimalAddress = BASE_ADDRESS + instructionCounter;
					strcpy(ExternLabels[externLabelCounter].name, currentCmd);
					externLabelCounter++;
					strcpy(Objects[instructionCounter].type, "e");
				}
				else
				{
					strcpy(Objects[instructionCounter].type, "r");
				}
			}
		}
		else
		{
			errorWasFound = true;
			printf("Illegal addressing method Direct for %s operand. Line number %d\n", operandTypesDesc[opType], lineNumber);
			return false;
		}
		return true;
	}

	/*check if operand is a valid number*/
	if(IsValidNumber(currentCmd, &number))
	{
		if(IsLegalAddressingMethod(cmdIndex, opType, Immediate))
		{
			if(opType == Source)
				Objects[currentInstructionCounter].machineCode = Objects[currentInstructionCounter].machineCode | (Immediate << 10);
			else
				Objects[currentInstructionCounter].machineCode = Objects[currentInstructionCounter].machineCode | (Immediate << 5);

			instructionCounter++;

			Objects[instructionCounter].machineCode = number & MASK_BITS;
			Objects[instructionCounter].decimalAddress= BASE_ADDRESS + instructionCounter;
			strcpy(Objects[instructionCounter].type, "a");
		}
		else
		{
			errorWasFound = true;
			printf("Illegal addressing method Immediate for %s operand. Line number %d\n", operandTypesDesc[opType], lineNumber);
			return false;
		}
		return true;

	}

	/*check if operand is indexed method*/
	if(IsIndexed(currentCmd, label, operand, dataIndex, Registers, Commands))
	{
		if(IsLegalAddressingMethod(cmdIndex, opType, Indexed))
		{
			if(opType == Source)
				Objects[currentInstructionCounter].machineCode = Objects[currentInstructionCounter].machineCode | (Indexed << 10);
			else
				Objects[currentInstructionCounter].machineCode = Objects[currentInstructionCounter].machineCode | (Indexed << 5);

			instructionCounter++;

			/*insert label*/
			Objects[instructionCounter].decimalAddress = BASE_ADDRESS + instructionCounter;
			if(passNumber == Second)/*in second pass we need to insert the label address*/
			{
				labelAddress = GetLabelAddress(label, Labels, ExternLabels);
				Objects[instructionCounter].machineCode  = labelAddress;

				/*address was not found*/
				if(labelAddress == -1)
				{
					printf("Could not find label %s address. Line number %d\n", currentCmd, lineNumber);
					return false;
				}
				/*external was found*/
				if(labelAddress == -2)
				{
					/*update extern label*/
					ExternLabels[externLabelCounter].decimalAddress = BASE_ADDRESS + instructionCounter;
					strcpy(ExternLabels[externLabelCounter].name, label);
					externLabelCounter++;
					strcpy(Objects[instructionCounter].type, "e");
				}
				else
				{
					strcpy(Objects[instructionCounter].type, "r");
				}
			}

			/*insert the value from memory by data index*/
			instructionCounter++;
			int labelIndex = FindLabel(operand + 1, Labels);
			if (labelIndex < 0)
			{
				printf("Could not find label %s for dynamic index. Line number %d\n", operand + 1, lineNumber);
				return false;
			}
			Objects[instructionCounter].machineCode = Labels[labelIndex].codeSize;
			Objects[instructionCounter].decimalAddress = BASE_ADDRESS + instructionCounter;
			strcpy(Objects[instructionCounter].type, "a");
		}
		else
		{
			errorWasFound = true;
			printf("Illegal addressing method Indexed for %s operand. Line number %d\n", operandTypesDesc[opType], lineNumber);
			return false;
		}
		return true;
	}
	printf("Could not parse operand. Line number %d\n", lineNumber);
	return false;
}

/*
boolean ParseTwoOperands()
Purpose: this method executes for commands that include two operands
How: get first operand and parse it as source operand
	 get second operand and parse it as destination operand
Parameters: Non.
return value: true if parsing was done successfully otherwiese false (enum boolean)
 */
boolean ParseTwoOperands()
{
	boolean res;

	char *operands= (fixedLine +(currentArg - fixedLine)) + strlen(currentArg)+1;/*get operands in line*/
	char copy[COMMAND_LINE_L];
	strcpy(copy, operands);
	currentCmd = strtok(copy, " ,");
	if(!currentCmd)
	{
		printf("Could not get source operand. Line number %d\n", lineNumber);
		return false;
	}
	res = ParseOperand(Source);
	if(!res)
	{
		printf("Could not parse source operand. Line number %d\n", lineNumber);
		return false;
	}
	currentCmd = strtok(NULL, " ,\t\n");/*get next operand*/
	if(!currentCmd)
	{
		printf("Could not get destination operand. Line number %d\n", lineNumber);
		return false;
	}

	res = ParseOperand(Destination);
	if(!res)
	{
		printf("Could not parse destination operand. Line number %d\n", lineNumber);
		return false;
	}

	return true;
}

/*
boolean ParseOneOperand()
Purpose: this method executes for commands that include one operand
How: get first operand and parse it as destination operand
Parameters: Non.
return value: true if parsing was done successfully otherwiese false (enum boolean)
 */
boolean ParseOneOperand()
{
	boolean res;
	char *operands= (fixedLine +(currentArg - fixedLine)) + strlen(currentArg)+1;
	char copy[COMMAND_LINE_L];
	strcpy(copy, operands);
	currentCmd = strtok(copy, " ,");

	if(!currentCmd)
	{
		printf("Could not get destination operand. Line number %d\n", lineNumber);
		return false;
	}

	res = ParseOperand(Destination);
	if(!res)
	{
		printf("Could not parse destination operand. Line number %d\n", lineNumber);
		return false;
	}
	return true;
}

/*
boolean ParseNoOperand()
Purpose: this method executes for commands with no operands
How: always return true
Parameters: Non.
return value: true (enum boolean)
 */
boolean ParseNoOperands()
{
	/*no need to parse just continue*/
	return true;
}

/*
boolean UpdateAddressForDataLabels()
Purpose: update the address for labels type data
How: looping on labels list find labels with data type and update the address
Parameters: Non.
return value: Non.
 */
void UpdateAddressForDataLabels()
{
	int i;
	for(i=0; i< LABELS_NUMBER && strlen(Labels[i].name)>0; i++)
	{
		/*update only labels in type data*/
		if(strncmp(Labels[i].type, DATA_CODE, strlen(DATA_CODE))==0)
		{
			Labels[i].decimalAddress = BASE_ADDRESS + Labels[i].value + instructionCounter;
		}
	}
}

/*
boolean UpdateEntryAddress()
Purpose: update the enteries address
How: looping on labels and get the requested address by label name
	 looping on enteries list, find entry by label name and update the address
Parameters: argument type, label name
return value: true if address was successfully updated otherwise false (enum boolean)
 */
boolean UpdateEntryAddress(ArgumentType argType, char *label)
{
	int address;
	int i;
	for(i=0; i< LABELS_NUMBER ;i++)
	{
		if(strlen(Labels[i].name) > 0 && strncmp(Labels[i].name, label, strlen(Labels[i].name)) == 0)
		{
			address = Labels[i].decimalAddress;/*get label address from labels list*/
			break;
		}
	}
	for(i=0; i < LABELS_NUMBER; i++)
	{
		if(strlen(EnteriesLabels[i].name)>0 && strncmp(EnteriesLabels[i].name, label, strlen(EnteriesLabels[i].name)) == 0)
		{
			EnteriesLabels[i].decimalAddress = address;/*update entry label address*/
			return true;
		}
	}

	return false;
}

/*
boolean UpdateExternAddress()
Purpose: update the enteries address
How: looping on externals list, find entern by label name and update the address to the given address
Parameters: externals list, label name, address
return value: true if address was successfully updated otherwise false (enum boolean)
 */
boolean UpdateExternAddredd(ExternLabelsList *exts, char *label, int address)
{
	int i;
	for(i=0; i < LABELS_NUMBER; i++)
	{
		if(strlen(exts[i].name) > 0 && strncmp(exts[i].name, label, strlen(exts[i].name)) == 0)
		{
			exts[i].decimalAddress = address;/*update extern label address*/
			return true;
		}
	}
	return false;
}

/*
boolean WriteFiles()
Purpose: write output files
How: if enteries and externals exist then write iutput files for entry and extern
	 then write the object file
	 each time set the file extension
Parameters: file name
return value: Non.
 */
void WriteFiles(char *fileName)
{
	char filePath[FILE_PATH_L];
	strcpy(filePath, fileName);
	if(externLabelCounter > 0)/*write extern file if externs exist*/
	{
		strcat(filePath, ".ext");
		WriteExternFile(filePath, ExternLabels, externLabelCounter);
	}
	if(entryLabelCounter > 0)/*write entry file if enteries exist*/
	{
		strcpy(filePath, fileName);
		strcat(filePath, ".ent");
		WriteEntryFile(filePath, EnteriesLabels, entryLabelCounter);
	}
	strcpy(filePath, fileName);
	strcat(filePath, ".ob");
	WriteObjectFile(filePath, Objects, memory, instructionCounter, dataCounter);
}
